package com.example.demo.web;

import com.alibaba.fastjson.JSON;
import com.example.demo.domain.CommonResult;
import com.example.demo.domain.ServerInfo;
import com.example.demo.domain.UserChannelInfo;
import com.example.demo.redis.RedisUtil;
import com.example.demo.server.WebsocketServer;
import com.example.demo.util.CacheUtil;
import com.example.demo.util.NetUtil;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/* ━━━━━━佛祖保佑━━━━━━
 *                  ,;,,;
 *                ,;;'(    社
 *      __      ,;;' ' \   会
 *   /'  '\'~~'~' \ /'\.)  主
 * ,;(      )    /  |.     义
 *,;' \    /-.,,(   ) \    码
 *     ) /       ) / )|    农
 *     ||        ||  \)
 *     (_\       (_\
 * ━━━━━━永无BUG━━━━━━
 * @author ：zjq
 * @date ：2021/4/7 1:20
 * @description: TODO     http://www.websocket-test.com    在线测试
 *                        {"content":"xxxx","toChannelId":"db3abfed"}   测试数据  toChannelId 在 redis 中
 * @version: V1.0
 * @slogan: 天下风云出我辈，一入代码岁月催
 */
@RestController
@RequestMapping
@Slf4j
public class WebSocketController {


    @Value("${netty.port}")
    private int port;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private WebsocketServer websocketServer;

    //默认线程池 先意思意思 这么用
    private static ExecutorService executorService = Executors.newCachedThreadPool();


    /**
     * 开启 netty
     *
     * @return
     */
    @RequestMapping("/openNettyServer")
    public CommonResult openNettyServer() {

        try {

            log.info("启动Netty服务，获取可用端口：{}", port);
            Future<Channel> future = executorService.submit(websocketServer);
            Channel channel = future.get();
            if (null == channel) {
                throw new RuntimeException("netty server open error channel is null");
            }
            while (!channel.isActive()) {
                log.info("启动Netty服务，循环等待启动...");
                Thread.sleep(500);
            }
            // 放入 缓存
            CacheUtil.serverInfoMap.put(port, new ServerInfo(NetUtil.getHost(), port, new Date()));
            CacheUtil.serverMap.put(port, websocketServer);

            log.info("启动Netty服务，完成：{}", channel.localAddress());
            return CommonResult.success();
        } catch (Exception e) {
            log.error("启动Netty服务失败", e);
            return CommonResult.failed(e.getMessage());
        }
    }

    /**
     * 关闭 netty
     *
     * @return
     */
    @RequestMapping("/closeNettyServer")
    public CommonResult closeNettyServer() {
        try {
            log.info("关闭Netty服务开始，端口：{}", port);
            WebsocketServer websocketServer = CacheUtil.serverMap.get(port);
            if (null == websocketServer) {
                CacheUtil.serverMap.remove(port);
                return CommonResult.success();
            }
            websocketServer.destroy();
            CacheUtil.serverMap.remove(port);
            CacheUtil.serverInfoMap.remove(port);
            log.info("关闭Netty服务完成，端口：{}", port);
            return CommonResult.success();
        } catch (Exception e) {
            log.error("关闭Netty服务失败，端口：{}", port, e);
            return CommonResult.failed();
        }
    }

    /**
     *  查 服务端 列表
     * @return
     */
    @RequestMapping("/queryNettyServerList")
    public Collection<ServerInfo> queryNettyServerList() {
        try {
            Collection<ServerInfo> serverInfos = CacheUtil.serverInfoMap.values();
            log.info("查询服务端列表。{}", JSON.toJSONString(serverInfos));
            return serverInfos;
        } catch (Exception e) {
            log.info("查询服务端列表失败。", e);
            return null;
        }
    }

    /**
     *  从 redis 查 用户管道
     * @return
     */
    @RequestMapping("/queryUserChannelInfoList")
    public List<UserChannelInfo> queryUserChannelInfoList() {
        try {
            log.info("查询用户列表信息开始");
            List<UserChannelInfo> userChannelInfoList = redisUtil.popList();
            log.info("查询用户列表信息完成。list：{}", JSON.toJSONString(userChannelInfoList));
            return userChannelInfoList;
        } catch (Exception e) {
            log.error("查询用户列表信息失败", e);
            return null;
        }
    }

}
